﻿/*************************************************************************************
 * 工    具：  HK_RandomRotOrScale
 * 
 * 描    述：  对选中的物体进行随机旋转和缩放
 * 
 * 版    本：  V1.0
 * 作    者：  周阿媛、谭潇杰、京产肠饭
 * 
 * 创    建：  2021/08/29  V1.0
 * 
 * 链    接：  https://gitee.com/JingChanChangFan/hk_-unity-tools
*************************************************************************************/

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace HKTools
{
    public class HK_RandomRotOrScale : EditorWindow
    {
        // 是否全局缩放
        bool isGlobalScale = true;

        // 旋转xyz轴锁定
        bool isCanRotX = false;
        bool isCanRotY = true;
        bool isCanRotZ = false;

        // 缩放xyz轴锁定
        bool isCanScaleX = false;
        bool isCanScaleY = false;
        bool isCanScaleZ = false;

        // xyz轴旋转最值
        float rotaY = 360;
        float rotaX = 360;
        float rotaZ = 360;

        // xyz轴缩放最值   
        Vector2 scaleX = Vector2.one;
        Vector2 scaleY = Vector2.one;
        Vector2 scaleZ = Vector2.one;

        // 整体缩放最值
        float scaleMin = 1;
        float scaleMax = 1;

        //选中的物体
        static GameObject[] selectedObjs;

        Dictionary<int, List<Vector3>> InitDataDic = new Dictionary<int, List<Vector3>>();

        Dictionary<int, GameObject> selectObjsDic = new Dictionary<int, GameObject>();

        [MenuItem("HKTools/Random RotOrScale (随机旋转缩放工具)", priority = HK_MenuPriority.HK_RandomRotOrScale)]
        static void Init()
        {
            HK_RandomRotOrScale random = GetWindow<HK_RandomRotOrScale>("RandomRotaOrScale");
            random.Show();
        }

        /// <summary>
        /// 随机缩放的EditorGUI绘制
        /// </summary>
        void DrawRandomScaleGUI()
        {
            EditorGUILayout.LabelField("● 随机缩放：", EditorStyles.boldLabel);

            isGlobalScale = EditorGUILayout.ToggleLeft("是否整体随机", isGlobalScale);

            EditorGUILayout.Space(2);

            if (isGlobalScale)
            {
                scaleMin = EditorGUILayout.FloatField("最小缩放倍数:", scaleMin <= 0.01f ? 0.01f : scaleMin);
                scaleMax = EditorGUILayout.FloatField("最大缩放倍数:", scaleMax <= scaleMin ? scaleMin : scaleMax);
            }
            else
            {
                EditorGUILayout.BeginHorizontal();
                isCanScaleX = EditorGUILayout.ToggleLeft("X轴", isCanScaleX, GUILayout.Width(60));
                isCanScaleY = EditorGUILayout.ToggleLeft("Y轴", isCanScaleY, GUILayout.Width(60));
                isCanScaleZ = EditorGUILayout.ToggleLeft("Z轴", isCanScaleZ, GUILayout.Width(60));
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.Space(2);

                EditorGUI.BeginDisabledGroup(!isCanScaleX);
                scaleX = EditorGUILayout.Vector2Field("X轴缩放倍数 Min&Max：", isCanScaleX ? scaleX : Vector2.one);

                scaleX.x = scaleX.x <= 0.01f ? 0.01f : scaleX.x;
                scaleX.y = scaleX.y <= 0.01f ? 0.01f : scaleX.y;

                scaleX.x = scaleX.x >= scaleX.y ? scaleX.y : scaleX.x;
                scaleX.y = scaleX.y <= scaleX.x ? scaleX.x : scaleX.y;

                EditorGUI.EndDisabledGroup();

                EditorGUI.BeginDisabledGroup(!isCanScaleY);
                scaleY = EditorGUILayout.Vector2Field("Y轴缩放倍数 Min&Max:", isCanScaleY ? scaleY : Vector2.one);

                scaleY.x = scaleY.x <= 0.01f ? 0.01f : scaleY.x;
                scaleY.y = scaleY.y <= 0.01f ? 0.01f : scaleY.y;

                scaleY.x = scaleY.x >= scaleY.y ? scaleY.y : scaleY.x;
                scaleY.y = scaleY.y <= scaleY.x ? scaleY.x : scaleY.y;

                EditorGUI.EndDisabledGroup();

                EditorGUI.BeginDisabledGroup(!isCanScaleZ);
                scaleZ = EditorGUILayout.Vector2Field("Z轴缩放倍数 Min&Max：", isCanScaleZ ? scaleZ : Vector2.one);

                scaleZ.x = scaleZ.x <= 0.01f ? 0.01f : scaleZ.x;
                scaleZ.y = scaleZ.y <= 0.01f ? 0.01f : scaleZ.y;

                scaleZ.x = scaleZ.x >= scaleZ.y ? scaleZ.y : scaleZ.x;
                scaleZ.y = scaleZ.y <= scaleZ.x ? scaleZ.x : scaleZ.y;

                EditorGUI.EndDisabledGroup();
            }

            EditorGUILayout.Space(2);

            if (GUILayout.Button("缩放"))
            {
                if (isGlobalScale)
                    SetScaleAll();
                else
                    SetScale();
            }
        }

        /// <summary>
        /// 随机旋转的EditorGUI绘制
        /// </summary>
        void DrawRandomRotGUI()
        {
            EditorGUILayout.LabelField("● 随机旋转：", EditorStyles.boldLabel);

            EditorGUILayout.BeginHorizontal();
            isCanRotX = EditorGUILayout.ToggleLeft("X轴", isCanRotX, GUILayout.Width(60));
            isCanRotY = EditorGUILayout.ToggleLeft("Y轴", isCanRotY, GUILayout.Width(60));
            isCanRotZ = EditorGUILayout.ToggleLeft("Z轴", isCanRotZ, GUILayout.Width(60));
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space(2);

            EditorGUI.BeginDisabledGroup(!isCanRotX);
            rotaX = EditorGUILayout.FloatField("X轴+-最大增量", isCanRotX ? rotaX : 360);
            EditorGUI.EndDisabledGroup();

            EditorGUI.BeginDisabledGroup(!isCanRotY);
            rotaY = EditorGUILayout.FloatField("Y轴+-最大增量", isCanRotY ? rotaY : 360);
            EditorGUI.EndDisabledGroup();

            EditorGUI.BeginDisabledGroup(!isCanRotZ);
            rotaZ = EditorGUILayout.FloatField("Z轴+-最大增量", isCanRotZ ? rotaZ : 360);
            EditorGUI.EndDisabledGroup();

            EditorGUILayout.Space(2);

            if (GUILayout.Button("旋转"))
            {
                SetRotate();
            }
        }

        void OnGUI()
        {
            if (Selection.gameObjects.Length > 0)
            {
                for (int i = 0; i < Selection.gameObjects.Length; i++)
                {
                    if (!selectObjsDic.ContainsKey(Selection.gameObjects[i].GetInstanceID()))
                    {
                        Selection.gameObjects[i].hideFlags = HideFlags.NotEditable;
                        selectObjsDic.Add(Selection.gameObjects[i].GetInstanceID(), Selection.gameObjects[i]);
                    }
                }
            }

            EditorGUILayout.Space(10);

            DrawRandomScaleGUI();

            EditorGUILayout.Space(10);

            DrawRandomRotGUI();

            Repaint();
        }

        // 指定轴向随机旋转
        void SetRotate()
        {
            if (Selection.gameObjects.Length == 0)
            {
                Debug.Log("<color=red>错误：</color>" + "没有选中物体！");
                return;
            }

            selectedObjs = Selection.gameObjects;

            for (int i = 0; i < selectedObjs.Length; i++)
            {
                SetInitData(selectedObjs[i].transform);
                Undo.RecordObject(selectedObjs[i].transform, "旋转");
                selectedObjs[i].gameObject.hideFlags = HideFlags.None;

                if (isCanRotX)
                    selectedObjs[i].transform.localEulerAngles = new Vector3(
                    InitDataDic[selectedObjs[i].transform.GetInstanceID()][0].x + Random.Range(-rotaX, rotaX),
                    selectedObjs[i].transform.localEulerAngles.y,
                    selectedObjs[i].transform.localEulerAngles.z);

                if (isCanRotY)
                    selectedObjs[i].transform.localEulerAngles = new Vector3(
                    selectedObjs[i].transform.localEulerAngles.x,
                    InitDataDic[selectedObjs[i].transform.GetInstanceID()][0].y + Random.Range(-rotaY, rotaY),
                    selectedObjs[i].transform.localEulerAngles.z);

                if (isCanRotZ)
                    selectedObjs[i].transform.localEulerAngles = new Vector3(
                    selectedObjs[i].transform.localEulerAngles.x,
                    selectedObjs[i].transform.localEulerAngles.y,
                    Random.Range(-rotaZ, rotaZ) + InitDataDic[selectedObjs[i].transform.GetInstanceID()][0].z);

                selectedObjs[i].gameObject.hideFlags = HideFlags.NotEditable;
            }
        }

        // 指定轴向随机缩放
        void SetScale()
        {
            selectedObjs = Selection.gameObjects;

            if (Selection.gameObjects.Length == 0)
            {
                Debug.Log("<color=red>错误：</color>" + "没有选中物体！");
                return;
            }

            for (int i = 0; i < selectedObjs.Length; i++)
            {
                SetInitData(selectedObjs[i].transform);
                selectedObjs[i].gameObject.hideFlags = HideFlags.None;
                Undo.RecordObject(selectedObjs[i].transform, "缩放");

                if (isCanScaleX)
                {
                    float randomValue = Random.Range(scaleX.x, scaleX.y);

                    selectedObjs[i].transform.localScale = new Vector3(
                    InitDataDic[selectedObjs[i].transform.GetInstanceID()][1].x * randomValue,
                    selectedObjs[i].transform.localScale.y,
                    selectedObjs[i].transform.localScale.z);
                }

                if (isCanScaleY)
                {
                    float randomValue = Random.Range(scaleY.x, scaleY.y);

                    selectedObjs[i].transform.localScale = new Vector3(
                    selectedObjs[i].transform.localScale.x,
                    InitDataDic[selectedObjs[i].transform.GetInstanceID()][1].y * randomValue,
                    selectedObjs[i].transform.localScale.z);
                }


                if (isCanScaleZ)
                {
                    float randomValue = Random.Range(scaleZ.x, scaleZ.y);

                    selectedObjs[i].transform.localScale = new Vector3(
                    selectedObjs[i].transform.localScale.x,
                    selectedObjs[i].transform.localScale.y,
                    InitDataDic[selectedObjs[i].transform.GetInstanceID()][1].z * randomValue);
                }


                selectedObjs[i].gameObject.hideFlags = HideFlags.NotEditable;
            }
        }

        // 整体随机缩放
        void SetScaleAll()
        {
            selectedObjs = Selection.gameObjects;

            if (Selection.gameObjects.Length == 0)
            {
                Debug.Log("<color=red>错误：</color>" + "没有选中物体！");
                return;
            }

            for (int i = 0; i < selectedObjs.Length; i++)
            {
                SetInitData(selectedObjs[i].transform);

                Undo.RecordObject(selectedObjs[i].transform, "缩放");
                selectedObjs[i].gameObject.hideFlags = HideFlags.None;

                float randomValue = Random.Range(scaleMin, scaleMax);

                selectedObjs[i].transform.localScale = new Vector3(
                InitDataDic[selectedObjs[i].transform.GetInstanceID()][1].x * randomValue,
                InitDataDic[selectedObjs[i].transform.GetInstanceID()][1].y * randomValue,
                InitDataDic[selectedObjs[i].transform.GetInstanceID()][1].z * randomValue);

                selectedObjs[i].gameObject.hideFlags = HideFlags.NotEditable;
            }

        }

        //记录选中物体的初始值
        void SetInitData(Transform tf)
        {
            if (!InitDataDic.ContainsKey(tf.GetInstanceID()))
            {
                InitDataDic.Add(tf.GetInstanceID(), new List<Vector3>() { tf.localEulerAngles, tf.localScale });
            }
        }

        void OnDestroy()
        {
            InitDataDic.Clear();

            if (selectObjsDic.Count > 0)
            {
                foreach (KeyValuePair<int, GameObject> item in selectObjsDic)
                {
                    item.Value.hideFlags = HideFlags.None;
                }
            }

            selectObjsDic.Clear();
        }
    }
}